package org.hin.programmering1.engine;

import java.awt.MouseInfo;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.LinkedList;

/**
 * Input class for handling java awt input
 * 
 * @author Meanz
 */
public class Input implements KeyListener, MouseListener, MouseMotionListener {

	private Object object = new Object();
	private static Input input;
	
	/**
	 * Mouse position etc
	 */
	private int mouseX, mouseY, mouseDX, mouseDY;
	
	/**
	 * Key Managing
	 */
	private LinkedList<Integer> keysPressed = new LinkedList<Integer>();
	private LinkedList<Integer> keysDown = new LinkedList<Integer>();
	private LinkedList<Integer> _q_keysDown = new LinkedList<Integer>();
	private LinkedList<Integer> _q_keysUp = new LinkedList<Integer>();
	/**
	 * Mouse button managing
	 */
	private LinkedList<Integer> mKeysPressed = new LinkedList<Integer>();
	private LinkedList<Integer> mKeysDown = new LinkedList<Integer>();
	private LinkedList<Integer> _q_mKeysDown = new LinkedList<Integer>();
	private LinkedList<Integer> _q_mKeysUp = new LinkedList<Integer>();
	
	public Input() {
		input = this;
	}
	
	public void update(int winX, int winY) {
		keysPressed.clear();
		
		/**
		 * Updates mouse position
		 */
		
		int mX = MouseInfo.getPointerInfo().getLocation().x - winX;
		int mY = MouseInfo.getPointerInfo().getLocation().y - winY;
		mouseDX = mouseX + mX;
		mouseDY = mouseY + mY;
		mouseX = mX;
		mouseY = mY;
		
		synchronized(input.object) {
			
			/**
			 * Keyboard managing
			 */
			while(!_q_keysDown.isEmpty()) {
				if(!keysPressed.contains(_q_keysDown.getFirst())
						&& !keysDown.contains(_q_keysDown.getFirst())) {
					keysPressed.push(_q_keysDown.pop());
					keysDown.add(keysPressed.getFirst());
				} else {
					_q_keysDown.pop();
				}
			}
			while(!_q_keysUp.isEmpty()) {
				keysDown.remove((Object)_q_keysUp.pop());
			}
			
			/**
			 * Mouse button managing
			 */
			while(!_q_mKeysDown.isEmpty()) {
				if(!mKeysPressed.contains(_q_mKeysDown.getFirst())
						&& !mKeysDown.contains(_q_mKeysDown.getFirst())) {
					mKeysPressed.push(_q_mKeysDown.pop());
					mKeysDown.add(mKeysPressed.getFirst());
				} else {
					_q_mKeysDown.pop();
				}
			}
			while(!_q_mKeysUp.isEmpty()) {
				mKeysDown.remove((Object)_q_mKeysUp.pop());
			}
		}
	}
	
	
	/**
	 * Get the X position of the mouse
	 * @return
	 * The mouse X position
	 */
	public static int getMouseX() {
		return input.mouseX;
	}
	
	/**
	 * Get the Y position of the mouse
	 * @return
	 * The mouse Y position
	 */
	public static int getMouseY() {
		return input.mouseY;
	}
	
	/**
	 * Get the delta X position of the mouse
	 * @return
	 * The delta X position of the mouse
	 */
	public static int getMouseDX() {
		return input.mouseDX;
	}
	
	/**
	 * Get the delta Y position of the mouse
	 * @return
	 * The delta Y position oft he mouse
	 */
	public static int getMouseDY() {
		return input.mouseDY;
	}
	
	
	
	/**
	 * Check if a keyboard button is pressed
	 * @param keyCode
	 * The key code to check for 
	 * @return
	 * Whether or not the key was pressed
	 */
	public static boolean isKeyPressed(int keyCode) {
		return input.keysPressed.contains(keyCode);
	}
	
	/**
	 * Check if a keyboard button is held down
	 * @param keyCode
	 * The key code to check for
	 * @return
	 * Whether or not the key was held down
	 */
	public static boolean isKeyDown(int keyCode) {
		return input.keysDown.contains(keyCode);
	}
	
	/**
	 * Check if a mouse button is pressed
	 * @param keyCode
	 * The mouse key to check for
	 * @return
	 * Whether or not the mouse key was pressed
	 */
	public static boolean isMousePressed(int keyCode) {
		return input.mKeysPressed.contains(keyCode);
	}
	
	/**
	 * Check if a mouse button is held down
	 * @param keyCode
	 * The mouse key to check for
	 * @return
	 * Whether or not the mouse key was held down
	 */
	public static boolean isMouseDown(int keyCode) {
		return input.mKeysPressed.contains(keyCode);
	}

	@Override
	public void mouseClicked(MouseEvent arg0) {
		// TODO Auto-generated method stub
		synchronized(object) {
			
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		synchronized(object) {
			_q_mKeysDown.add(arg0.getButton());
		}
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		synchronized(object) {
			_q_mKeysUp.add(arg0.getButton());
		}
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		synchronized(object) {
			_q_keysDown.add(arg0.getKeyCode());
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {
		// TODO Auto-generated method stub
		synchronized(object) {
			_q_keysUp.add(arg0.getKeyCode());
		}
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		synchronized(object) {
			
		}
	}

	@Override
	public void mouseDragged(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseMoved(MouseEvent arg0) {
	}
	
}
